#import "BlankScreenCheck.h"

// 5s大小的屏幕 loading:36*36，webView:320*504,loading占比0.8%。
// 只要同一种颜色占比超过99%可以认定为白屏。
// 加载失败显示失败页面，是94%，这种情况算加载失败，暂时不算白屏。
#define WEBVIEW_BLANK_PERCENT      0.90

#define WEBVIEW_CLIP_SIZE          5    //周边裁剪掉的像素
#define WEBVIEW_SAMPLE_OFFSET      10
#define WEBVIEW_THUMSIZE_MULTIPLE  1    //图片缩小后的宽度（高度根据图片大小登录缩放）
#define WEBVIEW_BLANK_MAX_PIXEL_COUNT  3    //白屏页面颜色最多3种


@implementation BlankScreenCheck

/** 检查WebView白屏
 @{
 @"":@"",
 @"":@"",
 @"consuming_time":@"",
 @"":@"",
 @"":@"",
 @"ret":@"0",
 @"":@""
 }
 */

+ (void)checkBlankWebView:(CGRect)webViewFrame
                    image:(UIImage *)image
              resultBlock:(void(^)(NSDictionary *))resultBlock
{
    if (image) {
        NSMutableDictionary *dicM = [[NSMutableDictionary alloc] initWithCapacity:9];
        CGSize webViewSize = webViewFrame.size;
        [dicM setValue:[NSString stringWithFormat:@"%f",webViewSize.height] forKey:@"blankH"];
        [dicM setValue:[NSString stringWithFormat:@"%f",webViewSize.width] forKey:@"blankW"];
        CGRect reactInset = CGRectMake(WEBVIEW_CLIP_SIZE, WEBVIEW_CLIP_SIZE,
                                       webViewSize.width-WEBVIEW_CLIP_SIZE*2,
                                       webViewSize.height-WEBVIEW_CLIP_SIZE*2);
        [BlankScreenCheck checkBlankView:reactInset dic:dicM image:image resultBlock:resultBlock];
    }else {
        if (resultBlock) {
            resultBlock(nil);
        }
    }
}

+ (void)checkBlankView:(CGRect)rectInset
                   dic:(NSMutableDictionary *)dic
                 image:(UIImage *)image
           resultBlock:(void(^)(NSDictionary *))resultBlock
{
    UIImage *screenshot = image;//[Utility screenshot:view];
    if (!screenshot) {
        if (resultBlock) {
            resultBlock(nil);
        }
        return;
    }
    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
    
    [BlankScreenCheck thumbImageContext:rectInset dic:dic image:screenshot block:^(CGContextRef context, CGSize thumbSize) {
        @autoreleasepool {
            //第二步 取像素值
            unsigned char* data = CGBitmapContextGetData(context);
            if (data == NULL){
                if (resultBlock) {
                    resultBlock(nil);
                }
                return;
            }
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                NSCountedSet *cls=[NSCountedSet setWithCapacity:thumbSize.width*thumbSize.height];
                
                int sample_offset = WEBVIEW_SAMPLE_OFFSET;
                int exclude_center_x = thumbSize.width/2;
                int exclude_center_y = thumbSize.height/2;
                int exclude_size = 19;//loading框的半径
                
                // 把图片分成sample_offset*sample_offset的格子，在每个格子里随机取出1个点。
                for (int x=sample_offset*2; x<thumbSize.width; x=x+sample_offset) {
                    for (int y=sample_offset*2; y<thumbSize.height; y=y+sample_offset) {
                        int randomOffset = arc4random()%sample_offset;
                        int point_x = x-randomOffset;
                        int point_y = y-randomOffset;
                        // 去除loading框
                        if ((point_x>exclude_center_x-exclude_size && point_x<exclude_center_x+exclude_size) && (point_y>exclude_center_y-exclude_size && point_y<exclude_center_y+exclude_size)) {
                            //                NSLog(@"------blank check-----loading:x:%d,y%d",point_x,point_y);
                            continue;
                        }
                        //Test
                        //            dispatch_async(dispatch_get_main_queue(), ^{
                        //                UIView *loadingView = [[UIView alloc] initWithFrame:CGRectMake(point_x, point_y, 1, 1)];
                        //                [loadingView setBackgroundColor:[UIColor blackColor]];
                        //                [view addSubview:loadingView];
                        //            });
                        //
                        int offset = 4*(point_x*point_y);
                        int red = data[offset];
                        int green = data[offset+1];
                        int blue = data[offset+2];
                        int alpha =  data[offset+3];
                        NSArray *clr=@[@(red),@(green),@(blue),@(alpha)];
                        [cls addObject:clr];
                    }
                }
                
                // 释放 context
                CGContextRelease(context);
                
                //第三步 找到出现次数最多的那个颜色
                NSEnumerator *enumerator = [cls objectEnumerator];
                NSArray *curColor = nil;
                
                NSArray *maxColor = nil;
                NSUInteger maxCount = 0;
                NSUInteger allCount = 0;
                
                while ( (curColor = [enumerator nextObject]) != nil )
                {
                    NSUInteger tmpCount = [cls countForObject:curColor];
                    allCount += tmpCount;
                    if ( tmpCount < maxCount ) continue;
                    maxCount=tmpCount;
                    maxColor=curColor;
                }
                CFAbsoluteTime endTime = CFAbsoluteTimeGetCurrent();
                //        UIColor *maxColorRGB = [UIColor colorWithRed:([maxColor[0] intValue]/255.0f) green:([maxColor[1] intValue]/255.0f) blue:([maxColor[2] intValue]/255.0f) alpha:([maxColor[3] intValue]/255.0f)];
                CGFloat blankPercent = (CGFloat)maxCount/allCount;
                //        NSLog(@"------blank check-----maxCount:%ld",maxCount);
                //        NSLog(@"------blank check-----totalCount:%ld",allCount);
                //        NSLog(@"------blank check-----calculateResult:%f%%",blankPercent*100);
                //        NSLog(@"------blank check-----calculateTime:%f",endTime-startTime);
                [dic setValue:[NSString stringWithFormat:@"%ld",maxCount]
                       forKey:@"most_rgb_pixel_num"];
                [dic setValue:[NSString stringWithFormat:@"%ld",allCount]
                       forKey:@"total_select_pexel"];
                [dic setValue:[NSString stringWithFormat:@"%f",blankPercent]
                       forKey:@"pure_colour_percent"];
                [dic setValue:[NSString stringWithFormat:@"r:%d g:%d b:%d a:%d",[maxColor[0] intValue], [maxColor[1] intValue], [maxColor[2] intValue],[maxColor[3] intValue]]
                       forKey:@"most_rgb_pixel"];
                [dic setValue:[NSString stringWithFormat:@"%f",endTime-startTime]?:@""
                       forKey:@"consuming_time"];
                
                if ([cls count] > WEBVIEW_BLANK_MAX_PIXEL_COUNT) {
                    [dic setValue:[NSNumber numberWithBool:NO] forKey:@"result"];
                }else if (blankPercent > WEBVIEW_BLANK_PERCENT) {
                    [dic setValue:[NSNumber numberWithBool:YES] forKey:@"result"];
                }else{
                    [dic setValue:[NSNumber numberWithBool:NO] forKey:@"result"];
                }
                if (resultBlock) {
                    resultBlock(dic);
                }
            });
        }
    }];
}

+ (void)thumbImageContext:(CGRect)rectInset
                      dic:(NSMutableDictionary *)dic
                    image:(UIImage *)image
                    block:(void(^)(CGContextRef context, CGSize thumbSize))block
{
    // iOS 11 会 crash 切换到主线生成缩略图
    dispatch_async(dispatch_get_main_queue(), ^{
        CGSize thumbSize = CGSizeMake(image.size.width/WEBVIEW_THUMSIZE_MULTIPLE,
                                      image.size.height/WEBVIEW_THUMSIZE_MULTIPLE);
#if __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_6_1
        int bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaPremultipliedLast;
#else
        int bitmapInfo = kCGImageAlphaPremultipliedLast;
#endif
        //第一步 先把图片缩小 加快计算速度. 但越小结果误差可能越大
        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGContextRef context = CGBitmapContextCreate(NULL,
                                                     thumbSize.width,
                                                     thumbSize.height,
                                                     8,//bits per component
                                                     thumbSize.width*4,
                                                     colorSpace,
                                                     bitmapInfo);
        
        CGRect drawRect = CGRectMake(0, 0, thumbSize.width, thumbSize.height);
        CGContextDrawImage(context, drawRect, image.CGImage);
        CGColorSpaceRelease(colorSpace);
        if (block) {
            block(context, thumbSize);
        }
    });
}


+ (UIImage *)screenshot:(UIView *)view {
    if (!view || !( view.bounds.size.height > WEBVIEW_SAMPLE_OFFSET*2 && view.bounds.size.width > WEBVIEW_SAMPLE_OFFSET*2)) {
        return nil;
    }
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

+ (UIImage *)screenshot:(UIView *)view rectInset:(CGRect)rectInset{
    UIImage *img = [BlankScreenCheck screenshot:view];
    UIImage *contentImage = [BlankScreenCheck getSubImage:rectInset image:img];
    return contentImage;
}

+ (UIImage *)getSubImage:(CGRect)rect image:(UIImage *)image
{
    if (!image) {
        return nil;
    }
    CGFloat scale = image.scale;
    CGRect scaleInset = CGRectMake(rect.origin.x*scale, rect.origin.y*scale, rect.size.width*scale, rect.size.height*scale);
    CGImageRef subImageRef = CGImageCreateWithImageInRect(image.CGImage, scaleInset);
    CGRect smallBounds = CGRectMake(0, 0, CGImageGetWidth(subImageRef), CGImageGetHeight(subImageRef));
    
    UIGraphicsBeginImageContext(smallBounds.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextDrawImage(context, smallBounds, subImageRef);
    UIImage* smallImage = [UIImage imageWithCGImage:subImageRef];
    UIGraphicsEndImageContext();
    
    return smallImage;
}

+ (UIImage *)scaleToSize:(CGSize)size image:(UIImage *)image
{
    CGFloat width = CGImageGetWidth(image.CGImage);
    CGFloat height = CGImageGetHeight(image.CGImage);
    float verticalRadio = size.height*1.0/height;
    float horizontalRadio = size.width*1.0/width;
    float radio = 1;
    if(verticalRadio>1 && horizontalRadio>1){
        radio = verticalRadio > horizontalRadio ? horizontalRadio : verticalRadio;
    }else{
        radio = verticalRadio < horizontalRadio ? verticalRadio : horizontalRadio;
    }
    width = width*radio;
    height = height*radio;
    int xPos = (size.width - width)/2;
    int yPos = (size.height-height)/2;
    // 创建一个bitmap的context
    // 并把它设置成为当前正在使用的context
    UIGraphicsBeginImageContext(size);
    // 绘制改变大小的图片
    [image drawInRect:CGRectMake(xPos, yPos, width, height)];
    // 从当前context中创建一个改变大小后的图片
    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    // 使当前的context出堆栈
    UIGraphicsEndImageContext();
    // 返回新的改变大小后的图片
    return scaledImage;
}

@end
